#include "buildpacket.h"
#include "checksum.h"
#include <ifaddrs.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <string.h>

//如果查找失败，得到空字符串
char* getLocalIP() {
    char* localIP = "";
    struct ifaddrs *ifaddr, *ifa;

    // 获取接口列表
    if (getifaddrs(&ifaddr) == -1) {
        perror("getifaddrs");
        return localIP;
    }

    // 遍历接口列表
    for (ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
        if (ifa->ifa_addr == nullptr) continue;

        // 过滤 IPv4 地址
        if (ifa->ifa_addr->sa_family == AF_INET) {
            struct sockaddr_in *addr = (struct sockaddr_in *)ifa->ifa_addr;
            char ip[INET_ADDRSTRLEN];
            inet_ntop(AF_INET, &(addr->sin_addr), ip, INET_ADDRSTRLEN);

            // 排除回环地址
            if (strcmp(ip, "127.0.0.1") != 0) {
                localIP = ip;
                break;
            }
        }
    }

    freeifaddrs(ifaddr);
    return localIP;
}

void setIPHeader(struct iphdr *ipHeader){
    // 填充IP头部
    ipHeader->ihl = 5; //ip首部长度
    ipHeader->version = 4; //版本号ipv4
    ipHeader->tos = 0; //服务类型，表示常规
    ipHeader->tot_len = htons(sizeof(dataPacket)); //总长度，包括ip头部和数据部分
    ipHeader->id = htons(12345); //端口号初始化为12345
    ipHeader->frag_off = 0; //偏移字段为0，表示没有分片
    ipHeader->ttl = 64; //可经过64个路由器
    ipHeader->protocol = IPPROTO_TCP; //设置上层协议为tcp
    ipHeader->check = 0; // 校验和初始化为0

    ipHeader->saddr = inet_addr(getLocalIP()); // 源IP地址
    // ipHeader->saddr = inet_addr(ipaddr); // 源IP地址
    //ipHeader->daddr = destAddr.sin_addr.s_addr; //目的ip地址
}

// 填充TCP头部，不设置标志位
void setTCPHeader(struct tcphdr *tcpHeader){

    tcpHeader->source = htons(12345); // 源端口号初始化为12345
    //tcpHeader->dest = destAddr.sin_port;

    tcpHeader->seq = htonl(0x12345678); //设置序列号为12345678
    tcpHeader->ack_seq = 0; //确认序列号初始化为0
    tcpHeader->doff = 5; //设置数据偏移为5，表示tcp头部长度为20字节

    //滑动窗口值
    tcpHeader->window = htons(512);  //设置滑动窗口大小为512，使用htons函数将主机字节序转换为网络字节序
    tcpHeader->urg_ptr = 0;  //紧急指针初始化为0
}

void setData(dataPacket* packet,int len,char* str){
    // 填充数据部分
    // memcpy(packet->data, str, len);

    packet->data = str;
    packet->size = len;
}

//保留校验位，目标主机，目标端口.源端口号设置为12345，使用本地ip
dataPacket* buildDataPacket(){
    char packet[BUFFER_SIZE];

    //整个数据包初始化为0
    memset(packet, 0, sizeof(packet));

    dataPacket *myDataPacket = (dataPacket *)packet;
    struct iphdr *ipHeader = &myDataPacket->ip;
    setIPHeader(ipHeader);
    struct tcphdr *tcpHeader = &myDataPacket->tcp;
    setTCPHeader(tcpHeader);

    //设置数据部分
    char *str = "AAAAA";
    int len = strlen(str)+1; //strlen不包括结束字符
    setData(myDataPacket,len,str);

    return myDataPacket;
}

//实际调用buildpacket，也可自行构造
dataPacket *buildDataPacket(int port, char *ip)
{
    dataPacket* packet = buildDataPacket();
    //设置ip
    packet->ip.daddr = inet_addr(ip);
    //设置端口号
    packet->tcp.dest = htons(port);

    //设置校验位
    packet->ip.check = ip_checksum((unsigned short*)&packet->ip,packet->ip.tot_len);
    tcp_checksum(&packet->ip,&packet->tcp,packet->data,packet->size);
    return packet;
}

